package com.hsjk.szwj.module.pay.controller.app.division;

import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.hsjk.szwj.framework.common.exception.ServiceException;
import com.hsjk.szwj.framework.common.exception.enums.GlobalErrorCodeConstants;
import com.hsjk.szwj.framework.common.util.spring.SpringBeansUtil;
import com.hsjk.szwj.module.pay.constant.PayOrderDivisionConstant;
import com.hsjk.szwj.module.pay.controller.AbstractPayOrderController;
import com.hsjk.szwj.module.pay.dal.dataobject.config.ChannelRetMsg;
import com.hsjk.szwj.module.pay.dal.dataobject.config.DivisionChannelNotifyModel;
import com.hsjk.szwj.module.pay.dal.dataobject.config.MchAppConfigContext;
import com.hsjk.szwj.module.pay.dal.dataobject.order.PayOrderDivisionRecordDO;
import com.hsjk.szwj.module.pay.dal.dataobject.system.MchAppDO;
import com.hsjk.szwj.module.pay.dal.dataobject.system.MchInfoDO;
import com.hsjk.szwj.module.pay.exception.ResponseException;
import com.hsjk.szwj.module.pay.service.AbstractDivisionRecordChannelNotifyService;
import com.hsjk.szwj.module.pay.service.ConfigContextQueryService;
import com.hsjk.szwj.module.pay.service.IMchAppService;
import com.hsjk.szwj.module.pay.service.IMchInfoService;
import com.hsjk.szwj.module.pay.service.PayOrderDivisionRecordService;
import com.hsjk.szwj.module.pay.service.PayOrderProcessService;
import io.swagger.v3.oas.annotations.tags.Tag;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.StringUtils;
import org.apache.commons.lang3.tuple.MutablePair;
import org.springframework.http.ResponseEntity;
import org.springframework.validation.annotation.Validated;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.ResponseBody;
import org.springframework.web.bind.annotation.RestController;

import javax.annotation.Resource;
import javax.servlet.http.HttpServletRequest;
import java.util.List;

/**
 * @author chenjiawei
 * @desc
 * @Date 2023/08/25 18:03
 **/
@Tag(name = "应用端 - 分账渠道侧的通知相关接口")
@RestController
@RequestMapping("/division")
@Validated
@Slf4j
public class DivisionRecordChannelNotifyController extends AbstractPayOrderController {
    @Resource
    private PayOrderDivisionRecordService payOrderDivisionRecordService;
    @Resource
    private ConfigContextQueryService configContextQueryService;
    @Resource
    private IMchInfoService mchInfoService;
    @Resource
    private IMchAppService mchAppService;

    /**
     * 异步回调入口
     **/
    @ResponseBody
    @RequestMapping(value = {"/divisionRecordChannelNotify/{ifCode}"})
    public ResponseEntity doNotify(HttpServletRequest request,
                                   @PathVariable("ifCode") String ifCode) {

        Long divisionBatchId = null;
        String logPrefix = "进入[" + ifCode + "]分账回调";
        log.info("===== {} =====", logPrefix);
        try {
            // 参数有误
            if (StringUtils.isEmpty(ifCode)) {
                return ResponseEntity.badRequest().body("ifCode is empty");
            }

            //查询支付接口是否存在
            AbstractDivisionRecordChannelNotifyService divisionNotifyService
                    = SpringBeansUtil.getBean(ifCode + "DivisionRecordChannelNotifyService",
                    AbstractDivisionRecordChannelNotifyService.class);

            // 支付通道接口实现不存在
            if (divisionNotifyService == null) {
                log.error("{}, interface not exists ", logPrefix);
                return ResponseEntity.badRequest().body("[" + ifCode + "] interface not exists");
            }

            // 解析批次号 和 请求参数
            MutablePair<Long, Object> mutablePair = divisionNotifyService.parseParams(request);
            if (mutablePair == null) {
                // 解析数据失败， 响应已处理
                log.error("{}, mutablePair is null ", logPrefix);
                //需要实现类自行抛出ResponseException, 不应该在这抛此异常。
                throw new ServiceException(GlobalErrorCodeConstants.BAD_REQUEST.getCode(),
                        "解析数据异常！");
            }

            //解析到订单号
            divisionBatchId = mutablePair.left;
            log.info("{}, 解析数据为：divisionBatchId:{}, params:{}", logPrefix, divisionBatchId, mutablePair.getRight());


            // 通过 batchId 查询出列表（ 注意：  需要按照ID 排序！！！！ ）
            List<PayOrderDivisionRecordDO> recordList
                    = payOrderDivisionRecordService.list(new LambdaQueryWrapper<PayOrderDivisionRecordDO>()
                    .eq(PayOrderDivisionRecordDO::getState, PayOrderDivisionConstant.STATE_ACCEPT)
                    .eq(PayOrderDivisionRecordDO::getBatchOrderId, divisionBatchId)
                    .orderByAsc(PayOrderDivisionRecordDO::getId)
            );

            // 订单不存在
            if (recordList == null || recordList.isEmpty()) {
                log.error("{}, 待处理订单不存在. divisionBatchId={} ", logPrefix, divisionBatchId);
                return divisionNotifyService.doNotifyOrderNotExists(request);
            }
            MchInfoDO mchInfoDO = mchInfoService.getMchInfoById(recordList.get(0).
                    getMchId());
            MchAppDO mchAppDO = mchAppService.getById(recordList.get(0).getAppId());
            //查询出商户应用的配置信息
            MchAppConfigContext mchAppConfigContext
                    = configContextQueryService.queryMchInfoAndAppInfo(mchInfoDO.
                    getId(), mchAppDO.getId());

            //调起接口的回调判断
            DivisionChannelNotifyModel notifyResult
                    = divisionNotifyService.doNotify(request, mutablePair.getRight(),
                    recordList, mchAppConfigContext);

            // 返回null 表明出现异常， 无需处理通知下游等操作。
            if (notifyResult == null || notifyResult.getApiRes() == null) {
                log.error("{}, 处理回调事件异常  notifyResult data error, notifyResult ={} ", logPrefix, notifyResult);
                //需要实现类自行抛出ResponseException, 不应该在这抛此异常。
                throw new ServiceException(GlobalErrorCodeConstants.BAD_REQUEST.getCode(),
                        "处理回调事件异常！");
            }

            if (notifyResult.getRecordResultMap() != null
                    && !notifyResult.getRecordResultMap().isEmpty()) {

                for (Long divisionId : notifyResult.getRecordResultMap().keySet()) {

                    // 单条结果
                    ChannelRetMsg retMsgItem = notifyResult.getRecordResultMap().get(divisionId);

                    // 明确成功
                    if (ChannelRetMsg.ChannelState.CONFIRM_SUCCESS == retMsgItem.getChannelState()) {

                        payOrderDivisionRecordService.updateRecordSuccessOrFailBySingleItem(divisionId,
                                PayOrderDivisionConstant.STATE_SUCCESS, retMsgItem.getChannelOriginResponse());

                    } else if (ChannelRetMsg.ChannelState.CONFIRM_FAIL == retMsgItem.getChannelState()) {
                        // 明确失败
                        payOrderDivisionRecordService.updateRecordSuccessOrFailBySingleItem(divisionId,
                                PayOrderDivisionConstant.STATE_FAIL, StringUtils.defaultIfEmpty(retMsgItem.getChannelErrMsg(),
                                        retMsgItem.getChannelOriginResponse()));
                    }

                }
            }

            log.info("===== {}, 通知完成。 divisionBatchId={}, parseState = {} =====", logPrefix, divisionBatchId, notifyResult);

            return notifyResult.getApiRes();

        } catch (ServiceException e) {
            log.error("{}, divisionBatchId={}, BizException", logPrefix, divisionBatchId, e);
            return ResponseEntity.badRequest().body(e.getMessage());

        } catch (ResponseException e) {
            log.error("{}, divisionBatchId={}, ResponseException", logPrefix, divisionBatchId, e);
            return e.getResponseEntity();

        } catch (Exception e) {
            log.error("{}, divisionBatchId={}, 系统异常", logPrefix, divisionBatchId, e);
            return ResponseEntity.badRequest().body(e.getMessage());
        }
    }
}
